package com.uroad.jilinpda.util;

import android.support.annotation.NonNull;
import android.util.Log;

import java.util.Comparator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 自定义线程池
 * @author Created by liangc on 2018/3/6.
 */

@SuppressWarnings("unused")
public class PriorityExecutor extends ThreadPoolExecutor {

    private static final String TAG = "PriorityExecutor";

    /**核心线程池大小*/
    private static final int CORE_POOL_SIZE = 5;
    /**最大线程池大小*/
    private static final int MAX_POOL_SIZE = 56;
    /**保存存活时间，当线程数大于corePoolSize的空闲线程能保持的最大时间，单位：ms*/
    private static final int KEEP_ALIVE = 1;
    /**主要获取添加任务*/
    private static final AtomicLong SEQ_SEED = new AtomicLong(0);

    private static PriorityExecutor mInstance;

    /**
     * 线程队列方式 true-先进先出 false-后进后出
     * */
    private static final boolean FO = true;

    public static PriorityExecutor getInstance() {
        if (mInstance == null) {
            mInstance = new PriorityExecutor(
                    CORE_POOL_SIZE,
                    MAX_POOL_SIZE,
                    KEEP_ALIVE,
                    TimeUnit.SECONDS,
                    new PriorityBlockingQueue<>(MAX_POOL_SIZE, FO ? FIFO : LIFO),
                    THREAD_FACTORY
                    );
        }
        return mInstance;
    }

    /**
     * 判断当前线程池是否繁忙
     * @return boolean true-繁忙，false-不繁忙
     */
    public boolean isBusy() {
        Log.e(TAG, "Active thread count : " + getActiveCount());
        return getActiveCount() >= getCorePoolSize();
    }

    /**
     * 提交任务
     * @param runnable 线程
     */
    @Override
    public void execute(Runnable runnable) {
        Log.e(TAG, "Active thread count : " + getActiveCount());
        if (runnable instanceof PriorityRunnable) {
            ((PriorityRunnable) runnable).seq = SEQ_SEED.getAndIncrement();
        }
        super.execute(runnable);
    }

    private PriorityExecutor(int corePoolSize,
                             int maximumPoolSize,
                             long keepAliveTime,
                             TimeUnit unit,
                             BlockingQueue<Runnable> workQueue,
                             ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    /**
     * 创建线程工厂
     */
    private static final ThreadFactory THREAD_FACTORY = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        @Override
        public Thread newThread(@NonNull Runnable runnable) {
            return new Thread(runnable, "etc_thread#" + mCount.getAndIncrement());
        }
    };


    /**
     * 线程队列方式 先进先出
     */
    private static final Comparator<Runnable> FIFO = new Comparator<Runnable>() {
        @Override
        public int compare(Runnable lhs, Runnable rhs) {
            if (lhs instanceof PriorityRunnable && rhs instanceof PriorityRunnable) {
                PriorityRunnable lpr = ((PriorityRunnable) lhs);
                PriorityRunnable rpr = ((PriorityRunnable) rhs);
                int result = lpr.priority.ordinal() - rpr.priority.ordinal();
                return result == 0 ? (int) (lpr.seq - rpr.seq) : result;
            } else {
                return 0;
            }
        }
    };

    /**
     * 线程队列方式 后进先出
     */
    private static final Comparator<Runnable> LIFO = new Comparator<Runnable>() {
        @Override
        public int compare(Runnable lhs, Runnable rhs) {
            if (lhs instanceof PriorityRunnable && rhs instanceof PriorityRunnable) {
                PriorityRunnable lpr = ((PriorityRunnable) lhs);
                PriorityRunnable rpr = ((PriorityRunnable) rhs);
                int result = lpr.priority.ordinal() - rpr.priority.ordinal();
                return result == 0 ? (int) (rpr.seq - lpr.seq) : result;
            } else {
                return 0;
            }
        }
    };

    /**
     * 线程优先级
     */
    public enum Priority {
        /**高优先级*/
        HIGH,
        /**中优先级*/
        NORMAL,
        /**低优先级*/
        LOW
    }

    class PriorityRunnable implements Runnable {
        /**
         * 任务优先级
         */
        public final Priority priority;
        /**
         * 任务真正执行者
         */
        private final Runnable runnable;
        /**
         * 任务唯一标示
         */
        /*package*/ long seq;

        public PriorityRunnable(Priority priority, Runnable runnable) {
            this.priority = priority == null ? Priority.NORMAL : priority;
            this.runnable = runnable;
        }

        @Override
        public final void run() {
            this.runnable.run();
        }
    }


}
